home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-02-01 | 66.5 KB | 2,495 lines |
- unit Graphics;
-
- {Graphics routines used by Image program}
-
- interface
-
- uses
- QuickDraw, Palettes, Picker, PrintTraps, globals, Utilities;
-
- procedure ShowLineWidth;
- function GetInterpolatedPixel (x, y: real): real;
- procedure GetObliqueLine (xstart, ystart, start: real; angle: extended; count: integer; var line: rLineType);
- procedure GetLengthOrPerimeter (var ulength, clength: real);
- procedure PlotLineProfile;
- procedure PlotArbitraryLine;
- procedure DrawPlot;
- procedure UpdatePlotWindow;
- procedure ShowValues;
- procedure ComputePlotMinAndMax;
- procedure SetupPlot (start: point; VerticalPlot: boolean);
- procedure MakePlotWindow (PlotLeft, PlotTop, PlotWidth, PlotHeight: integer);
- procedure DrawObject (obj: ObjectType; p1, p2: point);
- procedure DrawTools;
- function InvertingCalibrationFunction: boolean;
- procedure DrawHistogram;
- procedure DrawLabels (xL, yL, zL: str255);
- procedure ShowNextImage;
- procedure StackImages;
- procedure TileImages;
- function Duplicate (name: str255; SavingBlankField: boolean): boolean;
- procedure InvertPic;
- procedure ShowMessage (str: str255);
- procedure ShowTime (StartTicks: LongInt; r: rect; str: str255);
- procedure ShowFrameRate (str1: str255; StartTicks, nFrames: LongInt);
- procedure ConvertHistoToText;
- procedure ConvertPlotToText;
- procedure ConvertCalibrationCurveToText;
- procedure SetupUndoInfoRec;
- procedure ScaleAndRotate;
- procedure ActivateWindow;
- procedure UpdateResultsWindow;
- procedure ScrollResultsText;
- procedure UpdateResultsScrollBars;
- procedure InitResultsTextEdit (font, size: integer);
- procedure DoMouseDownInResults (loc: point);
- procedure AppendResults;
- procedure DeleteLines (first, last: integer);
- procedure UpdateList;
- procedure SelectSlice (i: integer);
- procedure ShowMeter;
- procedure UpdateMeter (percentdone: integer; str: str255);
- function RgnNotTooBig (Rgn1, Rgn2: RgnHandle): boolean;
- procedure MakeCoordinatesRelative;
- procedure MakeOutline (RoiKind: RoiTypeType);
- procedure ConvertCoordinates;
- function CoordinatesAvailable: boolean;
- function CoordinatesAvailableMsg: boolean;
- procedure DrawDropBox (r: rect);
- function PopUpMenu (theMenu: MenuHandle; left, top, PopUpItem: integer): integer;
- procedure GetDItemRect (d: DialogPtr; item: integer; var r: rect);
- procedure DrawPopUpText (str: str255; r: rect);
- procedure SetUProc (d: DialogPtr; item: integer; pptr: handle);
-
-
-
- implementation
-
-
- {$PUSH}
- {$D-}
-
- procedure DrawJustifiedReal (x, y: integer; r: extended);
- {Draws a right justified real number.}
- var
- str: str255;
- digits: integer;
- begin
- if abs(r) >= 1000.0 then
- digits := 0
- else
- digits := 2;
- RealToString(r, 1, digits, str);
- MoveTo(x - StringWidth(str), y);
- DrawString(str);
- end;
-
-
- procedure DrawVerticalString (x, y: integer; str: str255);
- var
- i: integer;
- begin
- MoveTo(x, y);
- for i := 1 to length(str) do begin
- MoveTo(x, y);
- DrawChar(str[i]);
- y := y + 9;
- end;
- end;
-
-
- procedure LabelProfilePlot;
- var
- str: str255;
- min, max: real;
- x, y: integer;
- begin
- min := PlotMin;
- max := PlotMax;
- DrawJustifiedReal(PlotLeftMargin - 2, PlotHeight - PlotBottomMargin, min);
- DrawJustifiedReal(PlotLeftMargin - 2, PlotTopMargin + 8, max);
- y := PlotTopMargin + (PlotHeight - (PlotTopMargin + PlotBottomMargin)) div 2 - length(PlotYUnits) * 9 div 2 + 6;
- DrawVerticalString(PlotLeftMargin - 15, y, PlotYUnits);
- MoveTo(PlotLeftMargin, PlotHeight - PlotBottomMargin + 11);
- DrawLong(0);
- if PlotScale <> 0.0 then
- RealToString((PlotCount - 1) * PlotScale, 1, Precision, str)
- else
- NumToString(PlotCount - 1, str);
- MoveTo(PlotWidth - PlotRightMargin - StringWidth(str) + 4, PlotHeight - PlotBottomMargin + 11);
- DrawString(str);
- x := PlotRightMargin + (PlotWidth - (PlotRightMargin + PlotLeftMargin)) div 2 - StringWidth(str) div 2;
- MoveTo(x, PlotHeight - PlotBottomMargin + 13);
- DrawString(PlotXUnits);
- end;
-
-
- procedure LabelCalibrationPlot;
- var
- pbottom, hloc, vloc, i: integer;
- letter: packed array[1..6] of char;
- begin
- pbottom := PlotHeight - PLotBottomMargin;
- DrawJReal(PlotLeftMargin, PlotTopMargin + 4, MaxValue, 2);
- DrawJReal(PlotLeftMargin, pbottom, MinValue, 2);
- MoveTo(PlotLeftMargin - 3, pbottom + 10);
- DrawString('0');
- MoveTo(PlotWidth - PlotRightMargin - 14, pbottom + 10);
- DrawString('255');
- MoveTo(PlotLeftMargin + 15, PlotTopMargin + 15);
- TextSize(12);
- case info^.fit of
- StraightLine:
- DrawString('y=a+bx');
- Poly2:
- DrawString('y=a+bx+cx^2');
- Poly3:
- DrawString('y=a+bx+cx^2+dx^3');
- Poly4:
- DrawString('y=a+bx+cx^2+dx^3+ex^4');
- Poly5:
- DrawString('y=a+bx+cx^2+dx^3+ex^4+fx^5');
- ExpoFit:
- DrawString('y=aexp(bx)');
- PowerFit:
- DrawString('y=ax^b');
- LogFit:
- DrawString('y=aln(bx)');
- RodbardFit:
- DrawString('y=c*((a-x)/(x-d))^(1/b)');
- UncalibratedOD:
- DrawString('y=log10(255/(255-x))');
- otherwise
- end;
- hloc := PlotWidth - PlotRightMargin + 5;
- vloc := PlotTopMargin + 25;
- letter := 'abcdef';
- MoveTo(hloc, vloc);
- with info^ do
- for i := 1 to nCoefficients do begin
- MoveTo(hloc, vloc);
- TextSize(12);
- DrawString(letter[i]);
- DrawString('=');
- TextSize(9);
- DrawReal(Coefficient[i], 1, 8);
- vloc := vloc + 15;
- end;
- if info^.fit <> UncalibratedOD then begin
- vloc := vloc + 25;
- MoveTo(hloc, vloc);
- DrawString('S.D.=');
- DrawReal(FitSD, 1, 4);
- vloc := vloc + 15;
- MoveTo(hloc, vloc);
- DrawString('R^2=');
- DrawReal(FitGoodness, 1, 4);
- end;
- end;
-
-
- procedure DrawPlot;
- var
- fRect: rect;
- begin
- SetRect(fRect, PlotLeftMargin, PlotTopMargin, PlotWidth - PlotRightMargin, PlotHeight - PlotBottomMargin);
- PenNormal;
- FrameRect(fRect);
- DrawPicture(PlotPICT, fRect);
- TextFont(ApplFont);
- TextSize(9);
- if WindowPeek(PlotWindow)^.WindowKind = ProfilePlotKind then begin
- if DrawPlotLabels then
- LabelProfilePlot
- end
- else
- LabelCalibrationPlot;
- end;
-
-
- procedure UpdatePlotWindow;
- begin
- SetPort(PlotWindow);
- EraseRect(PlotWindow^.portRect);
- DrawPlot;
- DrawMyGrowIcon(PlotWindow);
- end;
-
-
- procedure MakePlotWindow; {(PlotLeft, PlotTop, PlotWidth, PlotHeight: integer)}
- var
- PLotRect, pwrect, dwrect, srect: rect;
- overlapping: boolean;
- begin
- if PlotWindow = nil then begin
- SetRect(PlotRect, PlotLeft, PlotTop, PlotLeft + PlotWidth, PlotTop + PlotHeight);
- PlotWindow := NewWindow(nil, PlotRect, 'Plot', true, DocumentProc, nil, true, 0);
- end
- else begin
- GetWindowRect(PlotWindow, pwrect);
- GetWindowRect(info^.wptr, dwrect);
- overlapping := SectRect(pwrect, dwrect, srect);
- if overlapping then
- MoveWindow(PlotWindow, PlotLeft, PlotTop, false);
- SizeWindow(PlotWindow, PlotWidth, PlotHeight, false);
- end;
- end;
-
-
- procedure GetDiagLine (start, finish: Point; var count: integer; var data: LineType; OptionKey: boolean);
- var
- sum: LongInt;
- p: ptr;
- deltax, deltay, xinc, yinc, accumulator, i: integer;
- xloc, yloc, j: integer;
- average: boolean;
- buf, fline: LineType;
- begin
- average := LineWidth > 1;
- if OptionKey and average then
- for i := 0 to MaxLine do
- fline[i] := ForegroundIndex;
- count := 0;
- xloc := start.h;
- yloc := start.v;
- deltax := finish.h - xloc;
- deltay := finish.v - yloc;
- if (deltax = 0) and (deltay = 0) then begin
- data[count] := MyGetPixel(xloc, yloc);
- if OptionKey then
- PutPixel(xloc, yloc, ForegroundIndex);
- count := 1;
- exit(GetDiagLine);
- end;
- if deltax < 0 then begin
- xinc := -1;
- deltax := -deltax
- end
- else
- xinc := 1;
- if deltay < 0 then begin
- yinc := -1;
- deltay := -deltay
- end
- else
- yinc := 1;
- if DeltaX > DeltaY then begin {More horizontal}
- if average and (CurrentTool <> LineTool) then
- deltax := deltax + LineWidth;
- accumulator := deltax div 2;
- i := deltax;
- repeat
- if count < MaxLine then
- count := count + 1;
- accumulator := accumulator + deltay;
- if accumulator >= deltax then begin
- accumulator := accumulator - deltax;
- yloc := yloc + yinc
- end;
- xloc := xloc + xinc;
- if average then begin
- GetColumn(xloc, yloc, LineWidth, buf);
- if OptionKey then
- PutColumn(xloc, yloc, LineWidth, fline);
- sum := 0;
- for j := 0 to LineWidth - 1 do
- sum := sum + buf[j];
- data[count - 1] := round(sum / LineWidth);
- end
- else begin
- data[count - 1] := MyGetPixel(xloc, yloc);
- if OptionKey then
- PutPixel(xloc, yloc, ForegroundIndex);
- end;
- i := i - 1;
- until i = 0
- end
- else begin {More vertical}
- if average and (CurrentTool <> LineTool) then
- deltay := deltay + LineWidth;
- accumulator := deltay div 2;
- i := deltay;
- repeat
- if count < MaxLine then
- count := count + 1;
- accumulator := accumulator + deltax;
- if accumulator >= deltay then begin
- accumulator := accumulator - deltay;
- xloc := xloc + xinc
- end;
- yloc := yloc + yinc;
- if average then begin
- GetLine(xloc, yloc, LineWidth, buf);
- if OptionKey then
- PutLine(xloc, yloc, LineWidth, fline);
- sum := 0;
- for j := 0 to LineWidth - 1 do
- sum := sum + buf[j];
- data[count - 1] := round(sum / LineWidth);
- end
- else begin
- data[count - 1] := MyGetPixel(xloc, yloc);
- if OptionKey then
- PutPixel(xloc, yloc, ForegroundIndex);
- end;
- i := i - 1;
- until i = 0
- end;
- end;
-
-
- function GetInterpolatedPixel (x, y: real): real;
- var
- i, xbase, ybase: integer;
- LowerLeft, LowerRight, UpperLeft, UpperRight: integer;
- xfraction, yfraction, UpperAverage, LowerAverage: real;
- begin
- xbase := trunc(x);
- ybase := trunc(y);
- xFraction := x - xbase;
- yFraction := y - ybase;
- LowerLeft := MyGetPixel(xbase, ybase);
- LowerRight := MyGetPixel(xbase + 1, ybase);
- UpperRight := MyGetPixel(xbase + 1, ybase + 1);
- UpperLeft := MyGetPixel(xbase, ybase + 1);
- UpperAverage := UpperLeft + xfraction * (UpperRight - UpperLeft);
- LowerAverage := LowerLeft + xfraction * (LowerRight - LowerLeft);
- GetInterpolatedPixel := LowerAverage + yfraction * (UpperAverage - LowerAverage);
- end;
-
-
- function GetCInterpolatedPixel (x, y: real): real;
- var
- i, xbase, ybase: integer;
- LowerLeft, LowerRight, UpperLeft, UpperRight: real;
- xfraction, yfraction, UpperAverage, LowerAverage: real;
- begin
- xbase := trunc(x);
- ybase := trunc(y);
- xFraction := x - xbase;
- yFraction := y - ybase;
- LowerLeft := cvalue[MyGetPixel(xbase, ybase)];
- LowerRight := cvalue[MyGetPixel(xbase + 1, ybase)];
- UpperRight := cvalue[MyGetPixel(xbase + 1, ybase + 1)];
- UpperLeft := cvalue[MyGetPixel(xbase, ybase + 1)];
- UpperAverage := UpperLeft + xfraction * (UpperRight - UpperLeft);
- LowerAverage := LowerLeft + xfraction * (LowerRight - LowerLeft);
- GetCInterpolatedPixel := LowerAverage + yfraction * (UpperAverage - LowerAverage);
- end;
-
-
- procedure GetObliqueLine (xstart, ystart, start: real; angle: extended; count: integer; var line: rLineType);
- var
- i: integer;
- x, y, xinc, yinc: extended;
- IntegerStart: boolean;
- tLine: LineType;
- begin
- IntegerStart := (xstart = trunc(xstart)) and (ystart = trunc(ystart));
- if IntegerStart and (angle = 0.0) then begin
- GetLine(trunc(xstart), trunc(ystart), count, tLine);
- for i := 0 to count - 1 do
- line[i] := cvalue[tLine[i]];
- exit(GetObliqueLine);
- end;
- if IntegerStart and (angle = 270.0) then begin
- GetColumn(trunc(xstart), trunc(ystart), count, tLine);
- for i := 0 to count - 1 do
- line[i] := cvalue[tLine[i]];
- exit(GetObliqueLine);
- end;
- angle := (angle / 180.0) * pi;
- xinc := cos(angle);
- yinc := -sin(angle);
- x := xstart + start * xinc;
- y := ystart + start * yinc;
- if info^.DensityCalibrated then
- for i := 0 to count - 1 do begin
- line[i] := GetCInterpolatedPixel(x, y);
- x := x + xinc;
- y := y + yinc;
- end
- else
- for i := 0 to count - 1 do begin
- line[i] := GetInterpolatedPixel(x, y);
- x := x + xinc;
- y := y + yinc;
- end;
- end;
-
-
- procedure DrawTools;
- var
- tPort: GrafPtr;
- tool: ToolType;
- tpRect, sRect, dRect: rect;
- hloc, vloc: integer;
-
- procedure CopyToolBits (src, dst: rect; CopyMode: integer);
- begin
- hlock(handle(CGrafPort(ToolWindow^).PortPixMap));
- CopyBits(toolBits, BitMapHandle(CGrafPort(ToolWindow^).PortPixMap)^^, src, dst, CopyMode, nil);
- hunlock(handle(CGrafPort(ToolWindow^).PortPixMap));
- end;
-
- begin
- GetPort(tPort);
- SetPort(ToolWindow);
- tpRect := CGrafPort(ToolWindow^).portRect;
- pmForeColor(BlackIndex);
- pmBackColor(WhiteIndex);
- CopyToolBits(tpRect, tpRect, srcCopy);
- case LOIType of
- Straight:
- ;
- Freehand: begin
- SetRect(sRect, 46, 92, 62, 106);
- hloc := 27;
- vloc := 92;
- SetRect(dRect, hloc, vloc, hloc + 16, vloc + 14);
- CopyToolBits(sRect, dRect, SrcCopy);
- end;
- Segmented: begin
- SetRect(sRect, 46, 108, 62, 122);
- hloc := 27;
- vloc := 92;
- SetRect(dRect, hloc, vloc, hloc + 16, vloc + 14);
- CopyToolBits(sRect, dRect, SrcCopy);
- end;
- end;
- InvertRect(ToolRect[CurrentTool]);
- SetRect(sRect, 46, 226, 55, 233);
- hloc := 2;
- vloc := Lines[LineIndex].top - 4;
- SetRect(dRect, hloc, vloc, hloc + 9, vloc + 7);
- CopyToolBits(sRect, dRect, SrcCopy); {Check mark}
- pmForeColor(ForegroundIndex);
- SetRect(sRect, 46, 81, 57, 87);
- hloc := 4;
- vloc := 101;
- SetRect(dRect, hloc, vloc, hloc + 11, vloc + 6);
- CopyToolBits(sRect, dRect, SrcOr); {Brush color}
- pmForeColor(BackgroundIndex);
- SetRect(sRect, 46, 65, 61, 76);
- hloc := 3;
- vloc := 73;
- SetRect(dRect, hloc, vloc, hloc + 15, vloc + 11);
- CopyToolBits(sRect, dRect, SrcOr); {Eraser color}
- SetPort(tPort);
- end;
-
-
- procedure ShowLineWidth;
- begin
- LineIndex := LineWidth;
- if LineWidth = 6 then
- LineIndex := 5;
- if LineWidth > 6 then
- LineIndex := 6;
- DrawTools;
- end;
-
-
- procedure GetFatLine (xstart, ystart: real; angle: extended; count: integer; var line: rLineType);
- var
- i, j, xbase, ybase: integer;
- x, y, xinc, yinc, pAngle, xinc2, yinc2: real;
- sum, value: real;
- add: boolean;
- begin
- add := (angle > 90.0) and (angle <= 270.0);
- angle := (angle / 180.0) * pi;
- xinc := cos(angle);
- yinc := -sin(angle);
- if add then
- pAngle := angle + pi / 2.0
- else
- pAngle := angle - pi / 2.0;
- xinc2 := cos(pAngle);
- yinc2 := -sin(pAngle);
- for i := 0 to count - 1 do begin
- x := xstart;
- y := ystart;
- sum := 0.0;
- for j := 1 to LineWidth do begin
- if info^.DensityCalibrated then
- value := GetCInterpolatedPixel(x, y)
- else
- value := GetInterpolatedPixel(x, y);
- sum := sum + value;
- x := x + xinc2;
- y := y + yinc2;
- end;
- line[i] := sum / LineWidth;
- xstart := xstart + xinc;
- ystart := ystart + yinc;
- end;
- end;
-
-
- procedure ComputePlotMinAndMax;
- var
- i: integer;
- temp: real;
- begin
- ActualPlotMin := 10e12;
- ActualPlotMax := 10e-12;
- for i := 0 to PlotCount - 1 do begin
- temp := PlotData^[i];
- if temp < ActualPlotMin then
- ActualPlotMin := temp;
- if temp > ActualPlotMax then
- ActualPlotMax := temp;
- end;
- if InvertPlots then
- for i := 0 to PlotCount - 1 do
- PlotData^[i] := ActualPlotMax - (PlotData^[i] - ActualPlotMin);
- end;
-
-
- procedure SetupPlot (start: point; VerticalPlot: boolean);
- const
- MinWidth = 150;
- var
- fRect, trect: rect;
- i, y, WindowWidth, fmax: integer;
- SaveClipRegion: RgnHandle;
- pt: point;
- scale, vscale: real;
- AutoScale: boolean;
- index: UnsignedByte;
- begin
- with info^ do begin
- PlotLeftMargin := 38;
- PlotTopMargin := 10;
- PlotBottomMargin := 20;
- PlotRightMargin := 20;
- if FixedSizePlot then begin
- PlotWidth := ProfilePlotWidth;
- PlotHeight := ProfilePlotHeight
- end
- else begin
- PlotWidth := PlotCount * trunc(magnification + 0.5);
- if PlotWidth < MinWidth then
- PlotWidth := MinWidth;
- if PlotWidth + PlotRightMargin + PicLeftBase > ScreenWidth then
- PlotWidth := ScreenWidth - PlotRightMargin - PicLeftBase - 10;
- if PlotWidth > PicRect.right then
- PlotWidth := PicRect.right;
- PlotHeight := PlotWidth div 2;
- if PlotWidth > 300 then
- PlotHeight := PlotWidth div 3;
- if PlotWidth > 400 then
- PlotHeight := PlotWidth div 4;
- end;
- PlotWidth := PlotWidth + PlotLeftMargin + PlotRightMargin;
- PlotHeight := PlotHeight + PlotTopMargin + PlotBottomMargin;
- OffscreenToScreen(start);
- pt.h := start.h;
- pt.v := start.v + 40;
- SetPort(wptr);
- LocalToGlobal(pt);
- if VerticalPlot then
- PlotLeft := PicLeftBase
- else
- PlotLeft := pt.h - PlotLeftMargin;
- PlotTop := pt.v;
- if PlotLeft > (ScreenWidth - PlotWidth) then
- PlotLeft := ScreenWidth - PlotWidth - 10;
- if PlotTop < 60 then
- PlotTop := 60;
- if PlotTop > (ScreenHeight - PlotHeight) then
- PlotTop := ScreenHeight - PlotHeight - 10;
- if PlotTop < 60 then
- PlotTop := 60;
- MakePlotWindow(PlotLeft, PlotTop, PlotWidth, PlotHeight);
- if PlotWindow = nil then
- exit(SetupPlot);
- WindowPeek(PlotWindow)^.WindowKind := ProfilePlotKind;
- if SpatiallyCalibrated then begin
- PlotScale := 1 / xSpatialScale;
- if xUnit = 'inch' then
- PlotXUnits := 'Inches'
- else if xUnit = 'meter' then
- PlotXUnits := 'meters'
- else if xUnit = 'mile' then
- PlotXUnits := 'miles'
- else
- PlotXUnits := xUnit;
- end
- else begin
- PlotScale := 0.0;
- PlotXUnits := 'Pixels'
- end;
- if DensityCalibrated then
- PlotYUnits := UnitOfMeasure
- else
- PlotYUnits := '';
- if AutoScalePlots then begin
- PlotMin := ActualPlotMin;
- PlotMax := ActualPlotMax;
- end
- else begin
- PlotMin := ProfilePlotMin;
- PlotMax := ProfilePlotMax;
- end;
- fmax := PlotCount - 1;
- if (PlotMax - PlotMin) <> 0 then
- vscale := fmax / (PlotMax - PlotMin)
- else
- vscale := 1.0;
- scale := 2048.0 / PlotCount; {This scaling needed to get around a 32-bit QD problem}
- if scale < 1.0 then
- scale := 1.0;
- fmax := round(fmax * scale);
- vscale := vscale * scale;
- SetRect(fRect, 0, 0, fmax, fmax);
- SetPort(PlotWindow);
- SaveClipRegion := PlotWindow^.ClipRgn;
- RectRgn(PlotWindow^.ClipRgn, fRect);
- PlotPICT := OpenPicture(fRect);
- PenNormal;
- if LinePlot then begin
- MoveTo(0, round(vscale * (PlotMax - PlotData^[0])));
- for i := 1 to PlotCount - 1 do
- LineTo(round(i * scale), round(vscale * (PlotMax - PlotData^[i])))
- end
- else
- for i := 1 to PlotCount - 1 do begin
- y := round(vscale * (PlotMax - PlotData^[i]));
- MoveTo(round(i * scale), y);
- LineTo(round(i * scale), y)
- end;
- ClosePicture;
- PlotWindow^.ClipRgn := SaveClipRegion;
- InvalRect(PlotWindow^.PortRect);
- SelectWindow(PlotWindow);
- end; {with}
- end;
-
-
- procedure PlotLineProfile;
- var
- x1, y1, x2, y2, ulength, clength: real;
- start: point;
- begin
- GetLengthOrPerimeter(ulength, clength);
- PlotCount := round(ulength);
- if PlotCount = 0 then begin
- PutMessage('Line length is zero.');
- macro := false;
- exit(PlotLineProfile);
- end;
- GetLoi(x1, y1, x2, y2);
- PlotAngle := info^.LAngle;
- if LineWidth > 1 then
- GetFatLine(x1, y1, PlotAngle, PlotCount, PlotData^)
- else
- GetObliqueLine(x1, y1, 0.0, PlotAngle, PlotCount, PlotData^);
- PlotAvg := LineWidth;
- PlotStart.h := round(x1);
- PlotStart.v := round(y1);
- ComputePlotMinAndMax;
- if ShowPlot then
- SetupPlot(PlotStart, false);
- end;
-
-
- function CoordinatesAvailable: boolean;
- var
- available: boolean;
- begin
- with info^.RoiRect do
- available := (nCoordinates > 0) and ((right - left) = CoordinatesWidth) and ((bottom - top) = CoordinatesHeight) and (info^.RoiType = CoordinatesRoiType);
- if AnalyzingParticles and (nCoordinates > 0) then
- available := true;
- CoordinatesAvailable := available;
- end;
-
-
- function CoordinatesAvailableMsg: boolean;
- var
- available: boolean;
- begin
- available := CoordinatesAvailable;
- if not available then
- PutMessage('XY coordinates are not available.');
- CoordinatesAvailableMsg := available;
- end;
-
-
- function GetArbitraryLine (var count: integer; var pdata: rLineType): boolean;
- var
- angle, length, leftover: real;
- i, j, ilength, xbase, ybase: integer;
- x1, y1, x2, y2: LongInt;
- data: rLineType;
- begin
- if not CoordinatesAvailableMsg or (nCoordinates < 2) then begin
- GetArbitraryLine := false;
- exit(GetArbitraryLine);
- end;
- count := 0;
- length := 0.0;
- leftover := 0.0;
- with info^.RoiRect do begin
- xbase := left;
- ybase := top;
- end;
- for i := 2 to nCoordinates do begin
- x1 := xCoordinates^[i - 1] + xbase;
- y1 := yCoordinates^[i - 1] + ybase;
- x2 := xCoordinates^[i] + xbase;
- y2 := yCoordinates^[i] + ybase;
- length := sqrt(sqr(x2 - x1) + sqr(y2 - y1));
- if length > 0.0 then begin
- length := length - LeftOver;
- ilength := round(length);
- if ilength > 0 then begin
- GetAngle(x2 - x1, y1 - y2, angle);
- GetObliqueLine(x1, y1, leftover, angle, ilength, data);
- for j := 1 to ilength do begin
- pdata[count] := data[j - 1];
- count := count + 1;
- end;
- end;
- leftover := length - ilength;
- end;
- end;
- GetArbitraryLine := true;
- end;
-
-
- procedure PlotArbitraryLine;
- var
- angle, length, leftover: real;
- x1, y1, x2, y2, i, j, count: integer;
- data: LineType;
- begin
- if not GetArbitraryLine(PlotCount, PlotData^) then
- exit(PlotArbitraryLine);
- PlotAvg := 1;
- with info^.RoiRect do begin
- PlotStart.h := left;
- PlotStart.v := top;
- end;
- ComputePlotMinAndMax;
- if ShowPlot then
- SetupPlot(PlotStart, false);
- end;
-
-
- procedure FindIntegratedDensity (var IntDen, Background: extended);
- var
- i, MinLevel, MaxLevel, iback: integer;
- MaxCount: LongInt;
- h, h2: HistogramType;
- sum, wsum: extended;
-
- procedure SmoothHistogram;
- var
- i: integer;
- begin
- h2 := h;
- h[0] := (3 * h2[0] + h2[1]) div 5;
- for i := 1 to 254 do
- h[i] := (h2[i - 1] + 2 * h2[i] + h2[i + 1]) div 4;
- end;
-
- begin
- with results do begin
- MinLevel := MinIndex;
- MaxLevel := round(UncalibratedMean);
- if MaxLevel > 254 then
- MaxLevel := 254;
- h := histogram;
- for i := 0 to 255 do
- h[i] := h[i] * 10;
- for i := 1 to 15 do
- SmoothHistogram;
- if OptionKeyDown then
- histogram := h;
- Background := 0.0;
- MaxCount := 0;
- for i := MinLevel to MaxLevel do
- if h[i] > MaxCount then begin
- MaxCount := h[i];
- Background := cvalue[i]
- end;
- IntDen := mArea^[mCount] * (mean^[mCount] - Background);
- end;
- end;
-
- procedure ShowValues;
- var
- vloc, hloc: integer;
- tPort: GrafPtr;
- trect: rect;
- clength, cx, cy, IntDen, BackgroundLevel: extended;
- tUnit: UnitType;
-
- procedure NewLine;
- begin
- vloc := vloc + 12;
- MoveTo(hloc, vloc);
- end;
-
- begin
- GetPort(tPort);
- vloc := 35;
- hloc := 4;
- SetPort(ValuesWindow);
- TextFont(ApplFont);
- TextSize(9);
- Setrect(trect, 0, vloc, rwidth, rheight);
- EraseRect(trect);
- if ValuesMessage <> '' then begin
- Setrect(trect, hloc, vloc + 15, rwidth - 10, rheight);
- TextBox(pointer(ord(@ValuesMessage) + 1), length(ValuesMessage), trect, teJustLeft)
- end
- else
- with results do begin
- NewLine;
- with info^ do begin
- if ShowCount then begin
- DrawBString('Count: ');
- DrawLong(mCount);
- NewLine;
- end;
- if SpatiallyCalibrated then begin
- DrawBString('Pixels: ');
- DrawLong(PixelCount^[mCount]);
- NewLine;
- DrawBString('Area: ');
- DrawReal(mArea^[mCount], 1, precision);
- DrawString(' square ');
- tUnit := xUnit;
- if tUnit = 'inch' then
- tUnit := 'Inches'
- else if tUnit = 'meter' then
- tUnit := 'meters'
- else if tUnit = 'mile' then
- tUnit := 'miles';
- DrawString(tUnit);
- end
- else begin
- DrawBString('Area: ');
- DrawLong(PixelCount^[mCount]);
- DrawString(' square pixels');
- end;
- NewLine;
- DrawBString('Mean: ');
- DrawReal(mean^[mCount], 1, precision);
- if DensityCalibrated then begin
- DrawString(' ');
- DrawBString(UnitOfMeasure);
- DrawString(' (');
- DrawLong(round(results.UncalibratedMean));
- DrawString(')');
- end;
- if PixelCount^[mCount] > 1 then begin
- NewLine;
- DrawBString('Std Dev: ');
- DrawReal(sd^[mCount], 1, precision);
- NewLine;
- DrawBString('Min: ');
- DrawReal(mMin^[mCount], 1, precision);
- NewLine;
- DrawBString('Max: ');
- DrawReal(mMax^[mCount], 1, precision);
- end;
- if (xyLocM in measurements) or (nPoints > 0) then begin
- NewLine;
- DrawBString('X: ');
- DrawReal(xcenter^[mCount], 6, precision);
- NewLine;
- DrawBString('Y: ');
- DrawReal(ycenter^[mCount], 6, precision);
- end;
- if ModeM in Measurements then begin
- NewLine;
- DrawBString('Mode: ');
- DrawReal(mode^[mCount], 1, precision);
- end;
- if (LengthM in measurements) or (nLengths > 0) then begin
- NewLine;
- DrawBString('Length: ');
- DrawReal(plength^[mCount], 1, precision);
- end;
- if MajorAxisM in Measurements then begin
- NewLine;
- DrawBString(Concat(MajorLabel, ': '));
- DrawReal(MajorAxis^[mCount], 1, precision);
- end;
- if MinorAxisM in Measurements then begin
- NewLine;
- DrawBString(Concat(MinorLabel, ': '));
- DrawReal(MinorAxis^[mCount], 1, precision);
- end;
- if (AngleM in measurements) or (nAngles > 0) then begin
- NewLine;
- DrawBString('Angle: ');
- DrawReal(orientation^[mCount], 1, precision);
- end;
- if IntDenM in measurements then begin
- NewLine;
- FindIntegratedDensity(IntDen, BackgroundLevel);
- DrawBString('Integrated Density: ');
- DrawReal(IntDen, 1, precision);
- NewLine;
- DrawBString('Background Level: ');
- DrawReal(BackGroundLevel, 1, precision);
- end
- else begin
- IntDen := 0.0;
- BackGroundLevel := 0.0;
- end;
- IntegratedDensity^[mCount] := IntDen;
- idBackground^[mCount] := BackGroundLevel;
- if User1M in Measurements then begin
- NewLine;
- DrawBString(Concat(User1Label, ': '));
- DrawReal(User1^[mCount], 1, precision);
- end;
- if User2M in Measurements then begin
- NewLine;
- DrawBString(Concat(User2Label, ': '));
- DrawReal(User2^[mCount], 1, precision);
- end;
- end;
- end; {with}
- SetPort(tPort);
- mCount2 := mCount;
- end;
-
-
- procedure PaintCircle (hloc, vloc: integer);
- var
- r: rect;
- begin
- SetRect(r, hloc, vloc, hloc + LineWidth, vloc + LineWidth);
- PaintOval(r);
- end;
-
-
- procedure DrawBrush (start, finish: point);
- {Thanks to Robert Rimmer for suggesting the use of a line generator to implement the brush.}
- var
- deltax, deltay, xinc, yinc, accumulator, i: integer;
- xloc, yloc, offset, j: integer;
- begin
- xloc := start.h;
- yloc := start.v;
- deltax := finish.h - xloc;
- deltay := finish.v - yloc;
- if (deltax = 0) and (deltay = 0) then begin
- PaintCircle(xloc, yloc);
- exit(DrawBrush)
- end;
- if deltax < 0 then begin
- xinc := -1;
- deltax := -deltax
- end
- else
- xinc := 1;
- if deltay < 0 then begin
- yinc := -1;
- deltay := -deltay
- end
- else
- yinc := 1;
- if DeltaX > DeltaY then begin {More horizontal}
- accumulator := deltax div 2;
- i := deltax;
- repeat
- accumulator := accumulator + deltay;
- if accumulator >= deltax then begin
- accumulator := accumulator - deltax;
- yloc := yloc + yinc
- end;
- xloc := xloc + xinc;
- PaintCircle(xloc, yloc);
- i := i - 1;
- until i = 0
- end
- else begin {More vertical}
- accumulator := deltay div 2;
- i := deltay;
- repeat
- accumulator := accumulator + deltax;
- if accumulator >= deltay then begin
- accumulator := accumulator - deltay;
- xloc := xloc + xinc
- end;
- yloc := yloc + yinc;
- PaintCircle(xloc, yloc);
- i := i - 1;
- until i = 0
- end;
- end;
-
-
- procedure DrawObject;{ (obj: ObjectType; p1, p2: point)}
- var
- MaskRect, r, dstRect, osMaskRect: rect;
- tPort: GrafPtr;
- tmp: integer;
- begin
- GetPort(tPort);
- Pt2Rect(p1, p2, MaskRect);
- with Info^ do begin
- changes := true;
- tmp := trunc(magnification + 0.5) * LineWidth;
- with MaskRect do begin
- if tmp < 32 then
- tmp := 32;
- right := right + tmp;
- bottom := bottom + tmp;
- if magnification > 1.0 then begin
- left := left - tmp;
- top := top - tmp;
- end;
- end;
- ScreenToOffscreen(p1);
- ScreenToOffscreen(p2);
- SetPort(GrafPtr(osPort));
- pmForeColor(ForegroundIndex);
- PenNormal;
- PenSize(LineWidth, LineWidth);
- case obj of
- lineObj: begin
- MoveTo(p1.h, p1.v);
- LineTo(p2.h, p2.v);
- end;
- Rectangle: begin
- Pt2Rect(p1, p2, r);
- FrameRect(r);
- end;
- oval: begin
- Pt2Rect(p1, p2, r);
- FrameOval(r);
- end;
- BrushObj:
- DrawBrush(p1, p2);
- end;
- SetPort(wptr);
- pmForeColor(BlackIndex);
- pmBackColor(WhiteIndex);
- RectRgn(MaskRgn, MaskRect);
- hlock(handle(osPort^.portPixMap));
- hlock(handle(CGrafPort(wptr^).PortPixMap));
- CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, SrcCopy, MaskRgn);
- hunlock(handle(osPort^.portPixMap));
- hunlock(handle(CGrafPort(wptr^).PortPixMap));
- SetPort(tPort);
- end; {with}
- end;
-
-
- function InvertingCalibrationFunction: boolean;
- begin
- with info^ do begin
- InvertingCalibrationFunction := DensityCalibrated and (fit = StraightLine) and (Coefficient[2] < 0.0)
- end;
- end;
-
-
- procedure DrawHistogram;
- var
- tPort: GrafPtr;
- i, h: integer;
- MaxCount, count, NextMaxCount: LongInt;
- str: str255;
- hscale: extended;
- ShowSlice: boolean;
- begin
- ShowSlice := (HistogramSliceStart > 0) or (HistogramSliceEnd < 255);
- if not printing then begin
- GetPort(tPort);
- SetPort(HistoWindow);
- EraseRect(HistoWindow^.portRect);
- end;
- with Results do begin
- MaxCount := histogram[imode];
- if MaxCount > (hheight - 2) then begin
- if MaxCount / PixelCount^[mCount] > 0.08 then begin
- NextMaxCount := 0;
- for i := 0 to 255 do begin
- count := histogram[i];
- if (i <> imode) and (count > NextMaxCount) then
- NextMaxCount := count;
- end;
- NextMaxCount := NextMaxCount + NextMaxCount div 2;
- if (NextMaxCount > MaxCount) or (NextMaxCount = 0) then
- NextMaxCount := MaxCount;
- hscale := NextMaxCount / (hheight - 2);
- end
- else
- hscale := MaxCount / (hheight - 2);
- end
- else
- hscale := 1.0;
- if ShowSlice then
- PenPat(gray);
- if InvertingCalibrationFunction then
- for h := 0 to 255 do begin
- if h = HistogramSliceStart then
- PenPat(black);
- MoveTo(255 - h, hheight);
- LineTo(255 - h, hheight - round(histogram[h] / hscale));
- if h = HistogramSliceEnd then
- PenPat(gray)
- end
- else
- for h := 0 to 255 do begin
- if h = HistogramSliceStart then
- PenPat(black);
- MoveTo(h, hheight);
- LineTo(h, hheight - round(histogram[h] / hscale));
- if h = HistogramSliceEnd then
- PenPat(gray)
- end;
- end;
- if ShowSlice then
- PenNormal;
- if not Printing then
- SetPort(tPort);
- end;
-
-
- procedure DrawLabels (xL, yL, zL: str255);
- {Draws the labels(e.g., X:, Y:, Value:) used for the dynamically}
- {changing values displayed at the top of the Values window.}
- var
- tPort: GrafPtr;
- trect: rect;
- begin
- if xL = XLabel then
- if yL = yLabel then
- if zL = zLabel then
- exit(DrawLabels);
- GetPort(tPort);
- SetPort(ValuesWindow);
- TextSize(9);
- TextFont(Monaco);
- TextFace([bold]);
- if length(xL) > 0 then begin
- xLabel := xL;
- xValueLoc := ValuesHStart + StringWidth(xLabel);
- yLabel := yL;
- yValueLoc := ValuesHStart + StringWidth(yLabel);
- zLabel := zL;
- zValueLoc := ValuesHStart + StringWidth(zLabel);
- end;
- Setrect(trect, 0, 0, rwidth, 32);
- EraseRect(trect);
- MoveTo(ValuesHStart, ValuesVStart);
- DrawString(xLabel);
- MoveTo(ValuesHStart, ValuesVStart + 10);
- DrawString(yLabel);
- MoveTo(ValuesHStart, ValuesVStart + 19);
- DrawString(zLabel);
- TextFace([]);
- SetPort(tPort);
- end;
-
-
- procedure ShowNextImage;
- var
- n: integer;
- begin
- n := info^.PicNum + 1;
- if n > nPics then
- n := 1;
- SelectWindow(PicWindow[n]);
- end;
-
-
- procedure StackImages;
- var
- i, hloc, vloc, wwidth, wheight: integer;
- offset: boolean;
- begin
- hloc := PicLeftBase;
- vloc := PicTopBase;
- offset := not OptionKeyDown;
- for i := nPics downto 1 do begin
- Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
- if Info^.PictureType <> ScionType then begin
- with Info^ do begin
- HideWindow(wptr);
- ScaleToFitWindow := false;
- WindowState := NormalWindow;
- if offset then
- wrect := initwrect
- else begin
- wwidth := PixelsPerLine;
- if (hloc + wwidth) > ScreenWidth then
- wwidth := ScreenWidth - hloc - 5;
- wheight := nlines;
- if (vloc + wheight) > ScreenHeight then
- wheight := ScreenHeight - vloc - 5;
- SetRect(wrect, 0, 0, wwidth, wheight);
- end;
- SrcRect := wrect;
- KillRoi;
- magnification := 1.0;
- if i = nPics then
- DrawMyGrowIcon(wptr);
- SizeWindow(wptr, wrect.right, wrect.bottom, true);
- MoveWindow(wptr, hloc, vloc, true);
- ShowWindow(wptr);
- UpdateTitleBar;
- end;
- if offset then begin
- hloc := hloc + hPicOffset;
- vloc := vloc + vPicOffset;
- if (vloc + 40) > ScreenHeight then
- vloc := PicTopBase;
- end;
- end;
- end;
- PicLeft := PicLeftBase;
- PicTop := PicTopBase;
- WhatToUndo := NothingToUndo;
- end;
-
-
- procedure TileImages;
- const
- gap = 2;
- TitleBarHeight = 20;
- var
- i, hloc, vloc, width, height, hspace, vspace, nRows, nColumns: integer;
- MinWidth, MinHeight: integer;
- tInfo: array[1..MaxPics] of InfoPtr;
- trect: rect;
- TheyFit: boolean;
- begin
- PicLeft := PicLeftBase;
- PicTop := PicTopBase;
- width := MaxInt;
- height := MaxInt;
- for i := 1 to nPics do begin
- tInfo[i] := pointer(WindowPeek(PicWindow[i])^.RefCon);
- with tinfo[i]^.PicRect do begin
- if right < width then
- width := right;
- if bottom < height then
- height := bottom;
- end;
- end;
- MinWidth := width;
- MinHeight := height;
- hspace := ScreenWidth - PicLeft - 2 * gap;
- if width > hspace then
- width := hspace;
- vspace := ScreenHeight - PicTop - TitleBarHeight;
- if height > vspace then
- height := vspace;
- repeat
- hloc := PicLeft;
- vloc := PicTop;
- TheyFit := true;
- i := 0;
- repeat
- i := i + 1;
- if (hloc + width) > ScreenWidth then begin
- hloc := PicLeft;
- vloc := vloc + TitleBarHeight + height;
- if (vloc + height) > ScreenHeight then begin
- TheyFit := false;
- end;
- end;
- hloc := hloc + width + gap;
- until (TheyFit = false) or (i = nPics);
- if TheyFit = false then begin
- width := round(width * 0.98);
- height := round(height * 0.98);
- end;
- until TheyFit;
- nColumns := (ScreenWidth - PicLeft) div (width + gap);
- nRows := nPics div nColumns;
- if (nPics mod nColumns) <> 0 then
- nRows := nRows + 1;
- {ShowMessage(concat('nRows= ', Long2str(nRows), cr, 'nColumns= ', long2str(nColumns)));}
- if not OptionKeyWasDown then begin
- width := round((ScreenWidth - PicLeft) / nColumns);
- width := width - gap - 1;
- height := round((ScreenHeight - PicTop) / nRows);
- height := height - TitleBarHeight + 3;
- if width > MinWidth then
- width := MinWidth;
- if height > MinHeight then
- height := MinHeight;
- end;
- hloc := PicLeft;
- vloc := PicTop;
- for i := 1 to nPics do begin
- if (hloc + width) > ScreenWidth then begin
- hloc := PicLeft;
- vloc := vloc + TitleBarHeight + height;
- end;
- Info := tInfo[i];
- if Info^.PictureType <> ScionType then begin
- with Info^ do begin
- SetRect(wrect, 0, 0, width, height);
- if ScaleToFitWindow then begin
- ScaleToFitWindow := false;
- SrcRect := wrect;
- magnification := 1;
- WindowState := NormalWindow;
- end;
- if OptionKeyWasDown then begin
- ScaleToFitWindow := true;
- SrcRect := PicRect;
- ScaleImageWindow(wrect);
- WindowState := TiledSmallScaled;
- end
- else begin
- SrcRect := wrect;
- magnification := 1.0;
- UpdateTitleBar;
- WindowState := TiledSmall;
- end;
- SizeWindow(wptr, wrect.right, wrect.bottom, true);
- KillRoi;
- UpdatePicWindow;
- end;
- MoveWindow(PicWindow[i], hloc, vloc, true);
- hloc := hloc + width + gap;
- end;
- end; {for}
- WhatToUndo := NothingToUndo;
- end;
-
-
- function Duplicate (name: str255; SavingBlankField: boolean): boolean;
- var
- width, height, hstart, vstart, i: integer;
- SaveInfo: InfoPtr;
- src, dst: ptr;
- offset: LongInt;
- AutoSelectAll: boolean;
- begin
- Duplicate := false;
- if nPics = MaxPics then
- exit(Duplicate);
- WhatToUndo := NothingToUndo;
- if (not SavingBlankField) and (NotRectangular or NotinBounds) then
- exit(Duplicate);
- AutoSelectAll := (not Info^.RoiShowing) or SavingBlankField;
- if AutoSelectAll then
- SelectAll(false);
- ShowWatch;
- with info^ do begin
- if name = '' then begin
- name := concat('Copy of ', title);
- if length(name) > 32 then
- delete(name, 33, length(name) - 32);
- end;
- with RoiRect do begin
- width := right - left;
- if odd(width) then begin
- if (left + width < PicRect.right) then
- width := Width + 1
- else
- Width := width - 1;
- end;
- height := bottom - top;
- hstart := left;
- vstart := top;
- end;
- end;
- if AutoSelectAll then
- KillRoi;
- SaveInfo := Info;
- if NewPicWindow(name, width, height) then
- with SaveInfo^ do begin
- offset := LongInt(vstart) * BytesPerRow + hstart;
- src := ptr(ord4(PicBaseAddr) + offset);
- dst := Info^.PicBaseAddr;
- for i := 0 to height - 1 do begin
- BlockMove(src, dst, width);
- src := ptr(ord4(src) + BytesPerRow);
- dst := ptr(ord4(dst) + width);
- end;
- if SavingBlankField then begin
- Info^.PIctureType := BlankField;
- BlankFieldInfo := info;
- end;
- Duplicate := true;
- end; {with}
- end;
-
-
- procedure InvertPic;
- var
- tPort: GrafPtr;
- begin
- GetPort(tPort);
- with Info^ do begin
- SetPort(GrafPtr(osPort));
- InvertRect(PicRect);
- end;
- SetPort(tPort);
- end;
-
-
- procedure ShowMessage (str: str255);
- begin
- ValuesMessage := str;
- ShowValues;
- end;
-
-
- procedure ShowTime (StartTicks: LongInt; r: rect; str: str255);
- var
- nPixels: LongInt;
- str1, str2, str3: str255;
- seconds, rate: extended;
- begin
- with r do
- nPixels := LongInt(right - left) * (bottom - top);
- NumToString(nPixels, str1);
- seconds := (TickCount - StartTicks) / 60.0;
- RealToString(seconds, 1, 2, str2);
- if seconds <> 0.0 then
- rate := nPixels / seconds
- else
- rate := 0.0;
- NumToString(round(rate), str3);
- ShowMessage(concat(str1, ' pixels ', cr, str2, ' seconds', cr, str3, ' pixels/second', cr, str));
- end;
-
- procedure ShowFrameRate (str1: str255; StartTicks, nFrames: LongInt);
- var
- seconds: extended;
- str2: str255;
- begin
- seconds := (TickCount - StartTicks) / 60.0;
- if seconds = 0.0 then
- seconds := 0.167;
- RealToString(nFrames / seconds, 1, 2, str2);
- ShowMessage(concat(str1, str2, ' frames/second'));
- end;
-
-
- procedure ConvertHistoToText;
- var
- i: integer;
- ValuesInverted: boolean;
- begin
- ValuesInverted := InvertingCalibrationFunction;
- TextBufSize := 0;
- for i := 0 to 255 do begin
- if ValuesInverted then
- PutLong(Histogram[255 - i], 1)
- else
- PutLong(Histogram[i], 1);
- if i <> 255 then
- PutChar(cr);
- end;
- end;
-
-
- procedure ConvertPlotToText;
- var
- i: integer;
- begin
- TextBufSize := 0;
- for i := 0 to PlotCount - 1 do begin
- PutReal(PlotData^[i], 1, precision);
- if i <> PlotCount then
- PutChar(cr);
- end;
- end;
-
-
- procedure ConvertCalibrationCurveToText;
- var
- i: integer;
- begin
- TextBufSize := 0;
- for i := 0 to 255 do begin
- PutReal(cvalue[i], 1, 3);
- if i <> 255 then
- PutChar(cr);
- end;
- end;
-
-
- procedure SetupUndoInfoRec;
- {Initialize the Undo buffer's Info record so we can copy}
- {the current image to the Undo buffer and operate on it.}
- begin
- with UndoInfo^ do begin
- PixelsPerLine := info^.PixelsPerLine;
- BytesPerRow := info^.BytesPerRow;
- nLines := Info^.nLines;
- ImageSize := Info^.ImageSize;
- PixMapSize := info^.PixMapSize;
- RoiRect := info^.RoiRect;
- CopyRgn(Info^.roiRgn, roiRgn);
- roiType := Info^.roiType;
- PicRect := Info^.PicRect;
- with osPort^ do begin
- with portPixMap^^ do begin
- RowBytes := BitOr(BytesPerRow, $8000);
- bounds := PicRect;
- end;
- PortRect := PicRect;
- RectRgn(visRgn, PicRect);
- end;
- end;
- end;
-
-
- function GetScaleAndAngle: boolean;
- const
- hScaleID = 7;
- vScaleID = 8;
- AngleID = 9;
- NearestNeighborID = 10;
- BilinearID = 11;
- NewWindowID = 12;
- var
- mylog: DialogPtr;
- item, i: integer;
- vScaleUnchanged: boolean;
- str: str255;
- begin
- vScaleUnchanged := true;
- InitCursor;
- mylog := GetNewDialog(50, nil, pointer(-1));
- SetDReal(MyLog, AngleID, rsAngle, 2);
- SetDReal(MyLog, hScaleID, rsHScale, 2);
- SelIText(MyLog, hScaleID, 0, 32767);
- SetDReal(MyLog, vScaleID, rsVScale, 2);
- SetDialogItem(mylog, NewWindowID, ord(rsCreateNewWindow));
- SetDialogItem(mylog, BilinearID, ord(rsMethod = Bilinear));
- SetDialogItem(mylog, NearestNeighborID, ord(rsMethod = NearestNeighbor));
- repeat
- ModalDialog(nil, item);
- if item = AngleID then begin
- rsAngle := GetDREal(MyLog, AngleID);
- if rsAngle > 180.0 then
- rsAngle := 180.0;
- if rsAngle < -180.0 then
- rsAngle := -180.0;
- end;
- if item = hScaleID then begin
- str := GetDString(MyLog, hScaleID);
- rsHScale := StringToReal(str);
- if rsHScale = BadReal then
- rsHScale := 1.0;
- if vScaleUnchanged then begin
- rsVScale := rsHScale;
- SetDString(MyLog, vScaleID, str);
- end;
- if rsHScale < 0.05 then
- rsHScale := 0.05;
- end;
- if item = vScaleID then begin
- rsVScale := GetDReal(MyLog, vScaleID);
- if rsVScale = BadReal then
- rsVScale := 1.0;
- if rsVScale < 0.05 then
- rsVScale := 0.05;
- vScaleUnchanged := false;
- end;
- if item = NewWindowID then begin
- rsCreateNewWindow := not rsCreateNewWindow;
- SetDialogItem(mylog, NewWindowID, ord(rsCreateNewWindow));
- end;
- if (item = BilinearID) or (item = NearestNeighborID) then begin
- if item = BilinearID then
- rsMethod := Bilinear;
- if item = NearestNeighborID then
- rsMethod := NearestNeighbor;
- SetDialogItem(mylog, BilinearID, ord(rsMethod = Bilinear));
- SetDialogItem(mylog, NearestNeighborID, ord(rsMethod = NearestNeighbor));
- end;
- until (item = ok) or (item = cancel);
- DisposDialog(mylog);
- GetScaleAndAngle := item <> cancel;
- end;
-
-
- procedure ScaleAndRotate;
- const
- pi = 3.14159;
- type
- EraseType = (Erase, DontErase);
- var
- CosAngle, SinAngle, htemp, vtemp, h, v: extended;
- hloc, vloc, value, DstWidth, DstHeight, hstart, vstart, hend, vend: integer;
- hfraction, vfraction, UpperAverage, LowerAverage, AngleInRadians: extended;
- LowerLeft, LowerRight, UpperLeft, UpperRight, SaveWidth, SaveHeight: integer;
- hSrcCenter, vSrcCenter, hDstCenter, vDstCenter: integer;
- hRel, vRel, hbase, vbase, SrcWidth, SrcHeight: integer;
- SrcInfo, DstInfo, SaveInfo: InfoPtr;
- AutoSelectAll, UseNearestNeighbor, Rotate: boolean;
- MaskRect, SourceRect, DstRect: rect;
- StartTicks: LongInt;
- UseSameWindow: boolean;
-
- procedure DoInterpolatedScaling;
- {Does interpolated scaling, but no rotation, using scaled integer arithmetic.}
- const
- CountsPerUpdate = 5;
- var
- SrcLeft, hloc, vloc, vbase, hbase, hrel: integer;
- LineCount, oldvloc, LastLine: integer;
- DstLine, SrcLine1, SrcLine2: LineType;
- MaskRect: rect;
- v, SrcTop: extended;
- h, hFraction, vFraction, UpperAverage, LowerAverage: LongInt;
- scale, scale2, hscale: LongInt;
- begin
- scale := 1000;
- scale2 := scale * scale;
- hscale := round(rsHScale * scale);
- if SrcWidth >= MaxLine then
- exit(DoInterpolatedScaling);
- LastLine := SrcInfo^.PicRect.bottom - 1;
- with SourceRect do begin
- SrcLeft := left;
- SrcTop := top;
- end;
- with DstRect do begin
- oldvloc := top;
- LineCount := 0;
- for vloc := top to bottom - 1 do begin
- v := SrcTop + (vloc - top) / rsVScale;
- vbase := trunc(v);
- vFraction := round((v - vbase) * scale);
- Info := SrcInfo;
- GetLine(SrcLeft, vbase, SrcWidth, SrcLine1);
- SrcLine1[SrcWidth] := SrcLine1[SrcWidth - 1];
- if vbase <> LastLine then begin
- GetLine(SrcLeft, vbase + 1, SrcWidth, SrcLine2);
- SrcLine2[SrcWidth] := SrcLine2[SrcWidth - 1];
- end;
- for hloc := left to right - 1 do begin
- hrel := hloc - left;
- h := hrel * scale2 div hscale;
- hbase := hrel * scale div hscale;
- hFraction := h mod scale;
- LowerAverage := SrcLine1[hbase] + hFraction * (SrcLine1[hbase + 1] - SrcLine1[hbase]) div scale;
- UpperAverage := SrcLine2[hbase] + hFraction * (SrcLine2[hbase + 1] - SrcLine2[hbase]) div scale;
- DstLine[hrel] := (LowerAverage + vfraction * (UpperAverage - LowerAverage) div scale);
- end;
- Info := DstInfo;
- PutLine(left, vloc, DstWidth, DstLine);
- LineCount := LineCount + 1;
- if LineCount >= CountsPerUpdate then begin
- LineCount := 0;
- SetRect(MaskRect, left, oldvloc, right, vloc + 1);
- UpdateScreen(MaskRect);
- oldvloc := vloc;
- end;
- if CommandPeriod then begin
- beep;
- exit(DoInterpolatedScaling)
- end;
- end; {for vloc:=}
- SetRect(MaskRect, left, oldvloc, right, vloc + 1);
- UpdateScreen(MaskRect);
- end;
- end;
-
- procedure ScaleUsingCopyBits;
- var
- srcPort: cGrafPtr;
- SavePort: GrafPtr;
- MaskRect: rect;
- begin
- with DstInfo^ do begin
- GetPort(SavePort);
- SetPort(GrafPtr(osPort));
- pmForeColor(BlackIndex);
- pmBackColor(WhiteIndex);
- srcPort := SrcInfo^.osPort;
- hlock(handle(srcPort^.portPixMap));
- hlock(handle(osPort^.portPixMap));
- CopyBits(BitMapHandle(srcPort^.portPixMap)^^, BitMapHandle(osPort^.PortPixMap)^^, SourceRect, DstRect, SrcCopy, nil);
- hunlock(handle(srcPort^.portPixMap));
- hunlock(handle(osPort^.PortPixMap));
- pmForeColor(ForegroundIndex);
- pmBackColor(BackgroundIndex);
- SetPort(SavePort);
- end;
- if UseSameWindow then begin
- MaskRect := DstRect;
- UpdateScreen(MaskRect);
- end;
- end;
-
-
- begin
- if NotRectangular or NotInBounds then
- exit(ScaleAndRotate);
- if not (macro and not rsInteractive) then
- if not GetScaleAndAngle then
- exit(ScaleAndRotate);
- UpdatePicWindow;
- UseSameWindow := not rsCreateNewWindow;
- if UseSameWindow then
- with info^ do
- if NoUndo then begin
- macro := false;
- exit(ScaleAndRotate)
- end;
- with info^ do
- UseNearestNeighbor := rsMethod = NearestNeighbor;
- DrawTools;
- AutoSelectAll := not Info^.RoiShowing;
- if AutoSelectAll then
- SelectAll(true);
- ShowWatch;
- if UseSameWindow then begin
- SetupUndo;
- WhatToUndo := UndoEdit;
- SetupUndoInfoRec;
- SrcInfo := UndoInfo;
- DstInfo := Info;
- if rsAngle = 0.0 then
- DoOperation(EraseOp);
- end
- else
- SrcInfo := info;
- AngleInRadians := -((rsAngle + 270.0) / 360.0) * 2.0 * pi;
- CosAngle := cos(AngleInRadians);
- SinAngle := sin(AngleInRadians);
- with info^ do begin
- SourceRect := RoiRect;
- DstRect := RoiRect;
- end;
- with SourceRect do begin
- SrcWidth := right - left;
- SrcHeight := bottom - top;
- hSrcCenter := left + (SrcWidth div 2);
- vSrcCenter := top + (SrcHeight div 2);
- DstWidth := SrcWidth;
- DstHeight := SrcHeight;
- end;
- if UseSameWindow then
- with DstRect, info^ do begin
- if rsHScale <> 1.0 then begin
- DstWidth := round(SrcWidth * rsHScale);
- SaveWidth := DstWidth;
- left := left - (DstWidth - SrcWidth) div 2;
- if DstWidth > PicRect.right then
- DstWidth := PicRect.right;
- if left < 0 then
- left := 0;
- right := left + DstWidth;
- if DstWidth <> SaveWidth then begin
- SrcWidth := round(SrcWidth * (DstWidth / SaveWidth));
- SourceRect.left := hSrcCenter - SrcWidth div 2;
- SourceRect.right := SourceRect.left + SrcWidth;
- end;
- end;
- if rsVScale <> 1.0 then begin
- DstHeight := round(SrcHeight * rsVScale);
- SaveHeight := DstHeight;
- top := top - (DstHeight - SrcHeight) div 2;
- if DstHeight > PicRect.bottom then
- DstHeight := PicRect.bottom;
- if top < 0 then
- top := 0;
- bottom := top + DstHeight;
- if DstHeight <> SaveHeight then begin
- SrcHeight := round(SrcHeight * (DstHeight / SaveHeight));
- SourceRect.top := vSrcCenter - SrcHeight div 2;
- SourceRect.bottom := SourceRect.top + SrcHeight;
- end;
- end
- end {with}
- else begin
- DstWidth := round(SrcWidth * rsHScale);
- DstHeight := round(SrcHeight * rsVScale);
- if not NewPicWindow('Untitled', DstWidth, DstHeight) then begin
- KillRoi;
- exit(ScaleAndRotate)
- end;
- DstInfo := info;
- DstRect := info^.PicRect;
- end;
- with DstRect do begin
- hStart := left;
- vStart := top;
- hDstCenter := left + (DstWidth div 2);
- vDstCenter := top + (DstHeight div 2);
- end;
- hend := hstart + DstWidth - 1;
- vend := vstart + DstHeight - 1;
- rotate := rsAngle <> 0.0;
- ShowMessage(CmdPeriodToStop);
- StartTicks := TickCount;
- if not rotate and (rsMethod = NearestNeighbor) then
- ScaleUsingCopyBits
- else if not rotate and not UseNearestNeighbor then
- DoInterpolatedScaling
- else
- for vloc := vStart to vEnd do begin
- for hloc := hStart to hEnd do begin
- hrel := hloc - hDstCenter;
- vrel := vloc - vDstCenter;
- htemp := hrel * SinAngle + vrel * CosAngle;
- vtemp := vrel * SinAngle - hrel * CosAngle;
- htemp := htemp / rsHScale;
- vtemp := vtemp / rsVScale;
- h := htemp + hSrcCenter;
- v := vtemp + vSrcCenter;
- info := SrcInfo;
- if UseNearestNeighbor then
- value := MyGetPixel(round(h), round(v))
- else begin {Use bilinear interpolation}
- hbase := trunc(h);
- vbase := trunc(v);
- hFraction := h - hbase;
- vFraction := v - vbase;
- LowerLeft := MyGetPixel(hbase, vbase);
- LowerRight := MyGetPixel(hbase + 1, vbase);
- UpperRight := MyGetPixel(hbase + 1, vbase + 1);
- UpperLeft := MyGetPixel(hbase, vbase + 1);
- UpperAverage := UpperLeft + hfraction * (UpperRight - UpperLeft);
- LowerAverage := LowerLeft + hfraction * (LowerRight - LowerLeft);
- value := round(LowerAverage + vfraction * (UpperAverage - LowerAverage));
- end;
- Info := DstInfo;
- PutPixel(hloc, vloc, value);
- end; {for hloc:=}
- SetRect(MaskRect, hstart, vloc, hend, vloc + 1);
- UpdateScreen(MaskRect);
- if CommandPeriod then begin
- beep;
- KillRoi;
- exit(ScaleAndRotate)
- end;
- end; {for vloc:=}
- ShowTime(StartTicks, DstRect, '');
- KillRoi;
- with info^ do begin
- changes := true;
- if not UseSameWindow and (PixMapSize > UndoBufSize) then
- PutWarning;
- if SpatiallyCalibrated and (not UseSameWindow) then begin
- xSpatialScale := xSpatialScale * (DstWidth / SrcWidth);
- PixelAspectRatio := PixelAspectRatio * rsHScale / rsVScale;
- ySpatialScale := xSpatialScale / PixelAspectRatio;
- end;
- end;
- if not UseSameWindow and AutoSelectAll then begin
- SaveInfo := Info;
- Info := SrcInfo;
- KillRoi;
- Info := SaveInfo;
- end;
- if UseSameWindow then
- with NoInfo^ do begin
- roiType := RectRoi;
- RoiRect := DstRect;
- RectRgn(roiRgn, DstRect);
- end;
- end;
-
-
- {$POP}
-
-
- procedure ActivateWindow;
- var
- tPort: GrafPtr;
- begin
- with info^ do begin
- IsInsertionPoint := false;
- WhatToUndo := NothingToUndo;
- UndoFromClip := false;
- DrawLabels('', '', '');
- MouseState := NotInRoi;
- RoiUpdateTime := 0;
- if osPort <> nil then begin
- GetPort(tPort);
- SetPort(GrafPtr(osPort));
- pmForeColor(ForegroundIndex);
- pmBackColor(BackgroundIndex);
- SetPort(tPort);
- end;
- ShowRoi;
- end;
- end;
-
-
- procedure UpdateResultsWindow;
- begin
- SetPort(ResultsWindow);
- DrawControls(ResultsWindow);
- DrawGrowIcon(ResultsWindow);
- UpdateList;
- if ResultsWindow = FrontWindow then begin
- ShowControl(hScrollBar);
- ShowControl(vScrollBar);
- end
- else begin
- HideControl(hScrollBar);
- HideControl(vScrollBar);
- end;
- end;
-
-
- procedure ScrollResultsText;
- var
- value: INTEGER;
- begin
- with ListTE^^ do
- TEScroll((viewRect.left - destRect.left) - GetCtlValue(hScrollBar), (viewRect.top - destRect.top) - (GetCtlValue(vScrollBar) * LineHeight), ListTE);
- end;
-
-
- procedure UpdateResultsScrollBars;
- var
- vMax, vValue, hMax, hValue: integer;
- begin
- with ListTE^^, ListTE^^.viewRect do begin
- vListPageSize := (bottom - top) div LineHeight;
- hListPageSize := right - left;
- vMax := nLines - vListPageSize;
- hMax := (nListColumns + 1) * (FieldWidth + 1) * 6 - hListPageSize;
- vValue := (top - destRect.top) div LineHeight;
- hValue := left - destRect.left
- end;
- if vMax < 0 then
- vMax := 0;
- if vValue < 0 then
- vValue := 0;
- if hMax < 0 then
- hMax := 0;
- if vValue < 0 then
- vValue := 0;
- SetCtlMax(vScrollBar, vMax);
- SetCtlValue(vScrollBar, vValue);
- SetCtlMax(hScrollBar, hMax);
- SetCtlValue(hScrollBar, hValue);
- {ShowMessage(concat('nListColumns= ', Long2str(nListColumns), cr, 'hListPageSize= ', long2str(hListPageSize)));}
- end;
-
-
- procedure InitResultsTextEdit (font, size: integer);
- var
- dRect, vRect: rect;
- begin
- SetPort(ResultsWindow);
- with ResultsWindow^.portRect do
- SetRect(dRect, left + 4, top, right - 18, bottom - 24);
- vRect := dRect;
- ListTE := TENew(dRect, vRect);
- with ListTE^^ do begin
- TxFont := font;
- TxSize := size;
- crOnly := -1;
- end;
- if TextBufSize > 0 then begin
- TESetText(ptr(TextBufP), TextBufSize, ListTe);
- TECalText(ListTE);
- end;
- UpdateResultsScrollBars;
- end;
-
-
- procedure ScrAction (theCtl: ControlHandle; partCode: integer);
- var
- bInc, pInc, delta: integer;
- begin
- if theCtl = vScrollBar then begin
- bInc := 1;
- pInc := vListPageSize
- end
- else begin
- bInc := 4;
- pInc := hListPageSize
- end;
- case partCode of
- inUpButton:
- delta := -bInc;
- inDownButton:
- delta := bInc;
- inPageUp:
- delta := -pInc;
- inPageDown:
- delta := pInc;
- otherwise
- exit(ScrAction);
- end;
- SetCtlValue(theCtl, GetCtlValue(theCtl) + delta);
- ScrollResultsText;
- end;
-
-
- procedure DoMouseDownInResults (loc: point);
- var
- theCtl: ControlHandle;
- cValue: integer;
- begin
- SelectWindow(ResultsWindow);
- SetPort(ResultsWindow);
- GlobalToLocal(loc);
- case FindControl(loc, ResultsWindow, theCtl) of
- inUpButton, inDownButton, inPageUp, inPageDown:
- if TrackControl(theCtl, loc, @ScrAction) <> 0 then
- ;
- inThumb:
- if TrackControl(theCtl, loc, nil) <> 0 then
- ScrollResultsText;
- otherwise
- end;
- end;
-
-
- procedure AppendResults;
- var
- vMax: integer;
- begin
- if ResultsWindow <> nil then
- with ListTE^^ do begin
- if teLength > 32000 then
- exit(AppendResults);
- CopyResultsToBuffer(mCount, mCount, true);
- TESetSelect(teLength, teLength, ListTE);
- TEInsert(ptr(TextBufP), TextBufSize, ListTE);
- with ListTE^^ do begin
- vListPageSize := (viewRect.bottom - viewRect.top) div LineHeight;
- vMax := nLines - vListPageSize;
- end;
- if vMax < 0 then
- vMax := 0;
- SetCtlMax(vScrollBar, vMax);
- SetCtlValue(vScrollBar, GetCtlMax(vScrollBar));
- ScrollResultsText;
- end;
- end;
-
-
- procedure DeleteLines (first, last: integer);
- begin
- if ResultsWindow <> nil then
- with ListTE^^ do begin
- first := first + 2; {Accounts for 2 line header}
- last := last + 2;
- if (first = 3) and (last = 3) then
- first := 1; {if deleting first line then delete header too}
- if (first < 1) or (first > nLines) or (last < 1) or (last > nLines) then
- exit(DeleteLines);
- TESetSelect(LineStarts[first - 1], LineStarts[last], ListTE);
- TEDelete(ListTE);
- end;
- end;
-
-
- procedure UpdateList;
- begin
- if (ResultsWindow <> nil) and (mCount > 0) then
- with ListTE^^ do begin
- CopyResultsToBuffer(1, mCount, true);
- TESetSelect(0, teLength, ListTE);
- TEDelete(ListTE);
- TEInsert(ptr(TextBufP), TextBufSize, ListTE);
- UpdateResultsScrollBars;
- end;
- end;
-
-
- procedure SelectSlice (i: integer);
- begin
- with info^, info^.StackInfo^ do
- if i <= nSlices then begin
- hunlock(PicBaseHandle);
- PicBaseHandle := PicBaseH[i];
- hlock(PicBaseHandle);
- PicBaseAddr := StripAddress(PicBaseHandle^);
- osPort^.PortPixMap^^.BaseAddr := PicBaseAddr;
- end;
- end;
-
-
- procedure ShowMeter;
- const
- MeterWidth = 264;
- MeterHeight = 64;
- var
- trect: rect;
- hloc, vloc: integer;
- begin
- hloc := ScreenWidth div 2 - MeterWidth div 2;
- vloc := ScreenHeight div 4 - MeterHeight div 2;
- SetRect(trect, hloc, vloc, hloc + MeterWidth, vloc + MeterHeight);
- MeterWindow := NewWindow(nil, trect, '', true, dBoxProc, nil, false, 0);
- BringToFront(MeterWindow);
- end;
-
-
- procedure UpdateMeter; {(percentdone: integer; str: str255)}
- const
- left = 16;
- top = 28;
- right = 248;
- bottom = 44;
- var
- r: rect;
- begin
- if MeterWindow = nil then
- ShowMeter;
- if (percentdone >= 0) then begin
- SetPort(MeterWindow);
- TextFont(SystemFont);
- TextSize(12);
- TextMode(SrcCopy);
- MoveTo(left, top div 2);
- DrawString(str);
- SetRect(r, left + StringWidth(str), 0, right, top);
- EraseRect(r);
- SetRect(r, left, top, right, bottom);
- FrameRect(r);
- SetRect(r, left + 1, top + 1, left + (percentdone * (right - left)) div 100 - 1, bottom - 1);
- FillRect(r, gray);
- end {then}
- else begin
- DisposeWindow(MeterWindow);
- MeterWindow := nil;
- end; {else}
- end;
-
-
- function RgnNotTooBig; {(Rgn1, Rgn2: RgnHandle): boolean}
- begin
- RgnNotTooBig := GetHandleSize(handle(Rgn1)) + GetHandleSize(handle(Rgn2)) < 30000
- end;
-
-
- procedure GetSmoothedLength (var ulength, clength: real; FindPerimeter: boolean);
- {Finds the length of freehand line selections or perimeter of freehand}
- {or autotraced selections using a 3-point moving average.}
- var
- i, n: integer;
- x1, y1, x2, y2, dx, dy, xscale, yscale: real;
-
- procedure AddDelta;
- begin
- with info^ do begin
- dx := x2 - x1;
- dy := y2 - y1;
- uLength := uLength + sqrt(dx * dx + dy * dy);
- if SpatiallyCalibrated then begin
- dx := dx / xSpatialScale;
- dy := dy / ySpatialScale;
- cLength := cLength + sqrt(dx * dx + dy * dy);
- end;
- end;
- end;
-
- begin
- with info^ do begin
- uLength := 0.0;
- cLength := 0.0;
- n := nCoordinates;
- if not CoordinatesAvailable then
- exit(GetSmoothedLength);
- if FindPerimeter then begin
- x1 := (xCoordinates^[n] + xCoordinates^[1] + xCoordinates^[2]) / 3.0; {1}
- y1 := (yCoordinates^[n] + yCoordinates^[1] + yCoordinates^[2]) / 3.0;
- end
- else begin
- x1 := (xCoordinates^[1] * 2.0 + xCoordinates^[2]) / 3.0; {1}
- y1 := (yCoordinates^[1] * 2.0 + yCoordinates^[2]) / 3.0;
- end;
- x2 := (xCoordinates^[1] + xCoordinates^[2] + xCoordinates^[3]) / 3.0; {2}
- y2 := (yCoordinates^[1] + yCoordinates^[2] + yCoordinates^[3]) / 3.0;
- AddDelta;
- for i := 2 to n - 2 do begin
- x1 := x2; {i}
- y1 := y2;
- x2 := (xCoordinates^[i] + xCoordinates^[i + 1] + xCoordinates^[i + 2]) / 3.0; {i+1}
- y2 := (yCoordinates^[i] + yCoordinates^[i + 1] + yCoordinates^[i + 2]) / 3.0;
- AddDelta;
- end;
- x1 := x2; {n-1}
- y1 := y2;
- if FindPerimeter then begin
- x2 := (xCoordinates^[n - 1] + xCoordinates^[n] + xCoordinates^[1]) / 3.0; {n}
- y2 := (yCoordinates^[n - 1] + yCoordinates^[n] + yCoordinates^[1]) / 3.0;
- AddDelta;
- x1 := x2; {n}
- y1 := y2;
- x1 := (xCoordinates^[n] + xCoordinates^[1] + xCoordinates^[2]) / 3.0; {1}
- y1 := (yCoordinates^[n] + yCoordinates^[1] + yCoordinates^[2]) / 3.0;
- AddDelta;
- end
- else begin
- x2 := (xCoordinates^[n - 1] + xCoordinates^[n] * 2.0) / 3.0; {n}
- y2 := (yCoordinates^[n - 1] + yCoordinates^[n] * 2.0) / 3.0;
- AddDelta;
- end;
- if not SpatiallyCalibrated then
- cLength := uLength;
- end; {with}
- end;
-
-
- procedure GetLength (var ulength, clength: real; FindPerimeter: boolean);
- {Finds the length of segmented line selections or the perimeter of polygon selections.}
- var
- i: integer;
- xtemp, ytemp: LongInt;
- xt, yt: extended;
- begin
- with info^ do begin
- uLength := 0.0;
- cLength := 0.0;
- if not CoordinatesAvailable then
- exit(GetLength);
- for i := 2 to nCoordinates do begin
- xtemp := xCoordinates^[i] - xCoordinates^[i - 1];
- ytemp := yCoordinates^[i] - yCoordinates^[i - 1];
- uLength := uLength + sqrt(xtemp * xtemp + ytemp * ytemp);
- if SpatiallyCalibrated then begin
- xt := xtemp / xSpatialScale;
- yt := ytemp / ySpatialScale;
- cLength := cLength + sqrt(xt * xt + yt * yt);
- end;
- end;
- if FindPerimeter then begin
- xtemp := xCoordinates^[1] - xCoordinates^[nCoordinates];
- ytemp := yCoordinates^[1] - yCoordinates^[nCoordinates];
- uLength := uLength + sqrt(xtemp * xtemp + ytemp * ytemp);
- if SpatiallyCalibrated then begin
- xt := xtemp / xSpatialScale;
- yt := ytemp / ySpatialScale;
- cLength := cLength + sqrt(xt * xt + yt * yt);
- end;
- end;
- if not SpatiallyCalibrated then
- cLength := uLength;
- end; {with}
- end;
-
-
- procedure GetStraightLineLength (var ulength, clength: real);
- var
- dx, dy: extended;
- begin
- with info^ do begin
- dx := LX2 - LX1;
- dy := LY2 - LY1;
- uLength := sqrt(sqr(dx) + sqr(dy));
- if SpatiallyCalibrated then
- cLength := sqrt(sqr(dx / xSpatialScale) + sqr(dy / ySpatialScale))
- else
- cLength := uLength;
- end;
- end;
-
-
- procedure GetLengthOrPerimeter (var ulength, clength: real);
- begin
- case info^.RoiType of
- LineRoi:
- GetStraightLineLength(ulength, clength);
- PolygonRoi:
- GetLength(ulength, clength, true);
- FreehandRoi:
- GetSmoothedLength(ulength, clength, true);
- FreeLineRoi:
- GetSmoothedLength(ulength, clength, false);
- SegLineRoi:
- GetLength(ulength, clength, false);
- otherwise begin
- ulength := 0.0;
- clength := 0.0;
- end;
- end;
- end;
-
-
- procedure MakeCoordinatesRelative;
- var
- i: integer;
- begin
- with info^, info^.RoiRect do begin
- for i := 1 to nCoordinates do begin
- xCoordinates^[i] := xCoordinates^[i] - left;
- yCoordinates^[i] := yCoordinates^[i] - top;
- end;
- CoordinatesWidth := right - left;
- CoordinatesHeight := bottom - top;
- CoordinatesRoiType := RoiType;
- end;
- end;
-
-
- procedure MakeOutline (RoiKind: RoiTypeType);
- {Creates a "marching ants" outline from a list of absolute offscreen XY coordinates.}
- var
- i: integer;
- TempRgn: RgnHandle;
- spt, pt: point;
- begin
- with Info^ do begin
- if SelectionMode <> NewSelection then
- TempRgn := NewRgn;
- SetPort(wptr);
- PenNormal;
- OpenRgn;
- spt.h := xCoordinates^[1];
- spt.v := yCoordinates^[1];
- MoveTo(spt.h, spt.v);
- for i := 2 to nCoordinates do begin
- pt.h := xCoordinates^[i];
- pt.v := yCoordinates^[i];
- LineTo(pt.h, pt.v);
- end;
- LineTo(spt.h, spt.v);
- case SelectionMode of
- NewSelection:
- CloseRgn(roiRgn);
- AddSelection: begin
- CloseRgn(TempRgn);
- if RgnNotTooBig(roiRgn, TempRgn) then
- UnionRgn(roiRgn, TempRgn, roiRgn);
- nCoordinates := 0;
- end;
- SubSelection: begin
- CloseRgn(TempRgn);
- if RgnNotTooBig(roiRgn, TempRgn) then
- DiffRgn(roiRgn, TempRgn, roiRgn);
- nCoordinates := 0;
- end;
- end;
- RoiShowing := true;
- roiType := RoiKind;
- RoiRect := roiRgn^^.rgnBBox;
- UpdatePicWindow;
- end;
- if SelectionMode <> NewSelection then
- DisposeRgn(TempRgn);
- WhatToUndo := NothingToUndo;
- measuring := false;
- MakeCoordinatesRelative;
- end;
-
-
- procedure ConvertCoordinates;
- {Convert from screen to offscreen coordinates}
- var
- i: integer;
- begin
- with info^, info^.SrcRect do begin
- if (magnification <> 1.0) or (left <> 0) or (top <> 0) then begin
- if MakingLOI then
- for i := 1 to nCoordinates do begin
- xCoordinates^[i] := left + trunc(xCoordinates^[i] / magnification);
- yCoordinates^[i] := top + trunc(yCoordinates^[i] / magnification);
- end
- else
- for i := 1 to nCoordinates do begin
- xCoordinates^[i] := left + round(xCoordinates^[i] / magnification);
- yCoordinates^[i] := top + round(yCoordinates^[i] / magnification);
- end;
- end;
- end {with}
- end;
-
-
- procedure DrawTriangle (left, top: integer);
- var
- triangle: PolyHandle;
- begin
- triangle := OpenPoly;
- if triangle = nil then
- exit(DrawTriangle);
- MoveTo(left, top);
- LineTo(left + 12, top);
- LineTo(left + 6, top + 7);
- LineTo(left, top);
- ClosePoly;
- PaintPoly(triangle);
- KillPoly(triangle);
- end;
-
-
- procedure DrawDropBox (r: rect);
- {Draws the drop shadow box used for pop-up menus}
- begin
- with r do begin
- EraseRect(r);
- FrameRect(r);
- MoveTo(left + 2, bottom);
- LineTo(right, bottom);
- MoveTo(right, top + 2);
- LineTo(right, bottom);
- DrawTriangle(right - 15, top + 6);
- end;
- end;
-
-
- function PopUpMenu (theMenu: MenuHandle; left, top, PopUpItem: integer): integer;
- {Pops up the specified menu and returns item selected by user.}
- var
- PopupResult: LongInt;
- MenuLoc: point;
- begin
- with MenuLoc do begin
- h := left;
- v := top;
- LocalToGlobal(MenuLoc);
- PopUpResult := PopupMenuSelect(theMenu, v, h, PopUpItem);
- PopUpMenu := LoWord(PopUpResult);
- end;
- end;
-
-
- procedure GetDItemRect (d: DialogPtr; item: integer; var r: rect);
- var
- iType: integer;
- ignore: handle;
- begin
- GetDItem(d, item, itype, ignore, r)
- end;
-
-
- procedure DrawPopUpText (str: str255; r: rect);
- var
- TextRect: rect;
- begin
- with r do begin
- TextFont(SystemFont);
- if (str = '+') or (str = '╨') or (str = '╓') then begin
- TextSize(24);
- MoveTo(left + 13, bottom - 2);
- end
- else begin
- TextSize(12);
- MoveTo(left + 13, bottom - 5);
- end;
- if length(str) = 1 then
- DrawString(str)
- else begin
- SetRect(TextRect, left + 13, top + 1, right - 15, bottom - 1);
- TextBox(pointer(ord(@str) + 1), length(str), TextRect, TEJustLeft);
- end;
- end;
- end;
-
- procedure SetUProc (d: DialogPtr; item: integer; pptr: handle);
- var
- itype: integer;
- r: rect;
- h: handle;
- begin
- GetDItem(d, item, itype, h, r);
- SetDItem(d, item, itype, pptr, r);
- end;
-
-
- end.